package zhh.tangbao.machine.socket.server;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import zhh.tangbao.commodity.constant.ActivationState;
import zhh.tangbao.commodity.constant.MachineRunningState;
import zhh.tangbao.commodity.dao.CommodityMachineEntityDao;
import zhh.tangbao.commodity.manager.OrderPickUpManager;
import zhh.tangbao.machine.factory.MachineSocketClientFactory;
import zhh.tangbao.machine.manager.ConnectionManager;
import zhh.tangbao.machine.pojo.PreConnectionVerificationMachine;
import zhh.tangbao.machine.pojo.PreConnectionVerificationObject;
import zhh.tangbao.machine.socket.client.MachineSocketClient;
import zhh.tangbao.machine.util.MachineHolderUtil;
import zhh.tangbao.system.exception.ServiceException;
import zhh.tangbao.websocket.WebSocketSendMessageService;
import zhh.tangbao.websocket.WebSocketServiceType;
import zhh.tangbao.websocket.pojo.MachineRunning;
import zhh.tangbao.websocket.pojo.WebSocketMessageEntity;

import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;

/**
 * <p>
 *     描述
 * </p>
 * @author 粥灰灰
 * <p>2023/3/25</p>
 */

@Slf4j
@Component
public class MachineConnectServer {


    @Value("${custom.socket.port}")
    private int port;

    @Autowired
    private MachineSocketClientFactory factory;

    @Autowired
    private CommodityMachineEntityDao machineDao;

    @Autowired
    private ConnectionManager connectionManager;

    @Autowired
    private OrderPickUpManager orderPickUpManager;

    private Map<String, MachineSocketClient> machineSocketTaskMap;

    @Autowired
    private WebSocketSendMessageService webSocketServerManager;

    private ServerSocket server;

    private Thread serverThread;

    @Autowired
    private MachineHolderUtil util;

    @PostConstruct
    void init() throws IOException {
        this.machineSocketTaskMap = Maps.newConcurrentMap();
        startServer();
    }


    public void startServer() throws IOException {
        // 开启服务线程
        this.server = new ServerSocket(port);
        this.serverThread = new Thread(() -> {
            while (true) {
                try {
                    Socket client = this.server.accept();
                    Thread thread = new Thread(() -> {
                        try {
                            InputStream is = client.getInputStream();
                            InputStreamReader ir = new InputStreamReader(is);
                            BufferedReader reader = new BufferedReader(ir);
                            String s = reader.readLine();
                            PreConnectionVerificationObject o = JSONObject.parseObject(s, PreConnectionVerificationObject.class);
                            PreConnectionVerificationMachine machine = connectionManager.getACode(o.getVcode());
                            if (null == machine || !machine.getAcode().equals(o.getAcode())) {
                                client.close();
                                throw new ServiceException("验证码已过期或不正确");
                            }
                            connectionManager.removeVCode(o.getVcode());
                            MachineSocketClient c = factory.createClient(machine, client);
                            factory.scheduleTask(c);
                            orderPickUpManager.addMachine(machine.getMachineId());
                            this.machineSocketTaskMap.put(machine.getMachineId(), c);
                            util.addMachineKV(machine.getAcode(), machine.getMachineId());
                            machineDao.updateMachineRunningState(machine.getMachineId(), MachineRunningState.RUNNING);
                            machineDao.updateMachineActivationInfo(machine.getMachineId(), ActivationState.AC);
                            webSocketServerManager.sendMessageToAll(null, new WebSocketMessageEntity(WebSocketServiceType.MACHINE, new MachineRunning(machine.getMachineId(), MachineRunningState.RUNNING)));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    });
                    thread.start();
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            }
        });
        this.serverThread.start();
    }

}
